#if !defined(ximera_input_codes_hpp)
#define ximera_input_codes_hpp

// -----------------------------------------------------------

#include <ximera/config.hpp>
#include <ximera/enum.hpp>
#include <ximera/types.hpp>

namespace ximera { namespace input
{
    /*! \brief Codes of the buttons that can be used in a input device. 
     *
     * Used mainly in GamePads, Joysticks, Wheels, etc. 
     */
    XIMERA_ENUM(ButtonCode)
        Button0          = 0x00,
        Button1          = 0x01,
        Button2          = 0x02,
        Button3          = 0x03,
        Button4          = 0x04,
        Button5          = 0x05,
        Button6          = 0x06,
        Button7          = 0x07,
        Button8          = 0x08,
        Button9          = 0x09,
        Button10         = 0x0A,
        Button11         = 0x0B,
        Button12         = 0x0C,
        Button13         = 0x0D,
        Button14         = 0x0E,
        Button15         = 0x0F,
        Button16         = 0x10,
        Button17         = 0x11,
        Button18         = 0x12,
        Button19         = 0x13,
        Button20         = 0x14,
        Button21         = 0x15,
        Button22         = 0x16,
        Button23         = 0x17,
        Button24         = 0x18,
        Button25         = 0x19,
        Button26         = 0x1A,
        Button27         = 0x1B,
        Button28         = 0x1C,
        Button29         = 0x1D,
        Button30         = 0x1E,
        Button31         = 0x1F
    XIMERA_ENUM_END(ButtonCode)

    //! \brief Codes of the keys that can be used in a Keyboard input device.
    XIMERA_ENUM(KeyCode)
    #if defined(XIMERA_WIN32)
        Escape          = 0x01,
        _1              = 0x02,
        _2              = 0x03,
        _3              = 0x04,
        _4              = 0x05,
        _5              = 0x06,
        _6              = 0x07,
        _7              = 0x08,
        _8              = 0x09,
        _9              = 0x0A,
        _0              = 0x0B,
        Minus           = 0x0C,    /* - on main keyboard */
        Equals          = 0x0D,
        Back            = 0x0E,    /* backspace */
        Tab             = 0x0F,
        Q               = 0x10,
        W               = 0x11,
        E               = 0x12,
        R               = 0x13,
        T               = 0x14,
        Y               = 0x15,
        U               = 0x16,
        I               = 0x17,
        O               = 0x18,
        P               = 0x19,
        LBracket        = 0x1A,
        RBracket        = 0x1B,
        Return          = 0x1C,    /* Enter on main keyboard */
        LControl        = 0x1D,
        A               = 0x1E,
        S               = 0x1F,
        D               = 0x20,
        F               = 0x21,
        G               = 0x22,
        H               = 0x23,
        J               = 0x24,
        K               = 0x25,
        L               = 0x26,
        Semicolon       = 0x27,
        Apostrophe      = 0x28,
        Grave           = 0x29,    /* accent grave */
        LShift          = 0x2A,
        BackSlash       = 0x2B,
        Z               = 0x2C,
        X               = 0x2D,
        C               = 0x2E,
        V               = 0x2F,
        B               = 0x30,
        N               = 0x31,
        M               = 0x32,
        Comma           = 0x33,
        Period          = 0x34,    /* . on main keyboard */
        Slash           = 0x35,    /* / on main keyboard */
        RShift          = 0x36,
        Multiply        = 0x37,    /* * on numeric keypad */
        LMenu           = 0x38,    /* left Alt */
        Space           = 0x39,
        Capital         = 0x3A,
        F1              = 0x3B,
        F2              = 0x3C,
        F3              = 0x3D,
        F4              = 0x3E,
        F5              = 0x3F,
        F6              = 0x40,
        F7              = 0x41,
        F8              = 0x42,
        F9              = 0x43,
        F10             = 0x44,
        NumLock         = 0x45,
        Scroll          = 0x46,    /* Scroll Lock */
        NumPad7         = 0x47,
        NumPad8         = 0x48,
        NumPad9         = 0x49,
        Subtract        = 0x4A,    /* - on numeric keypad */
        NumPad4         = 0x4B,
        NumPad5         = 0x4C,
        NumPad6         = 0x4D,
        Add             = 0x4E,    /* + on numeric keypad */
        NumPad1         = 0x4F,
        NumPad2         = 0x50,
        NumPad3         = 0x51,
        NumPad0         = 0x52,
        Decimal         = 0x53,    /* . on numeric keypad */
        OEM_102         = 0x56,    /* <> or \| on RT 102-key keyboard (Non-U.S.) */
        F11             = 0x57,
        F12             = 0x58,
        F13             = 0x64,    /*                     (NEC PC98) */
        F14             = 0x65,    /*                     (NEC PC98) */
        F15             = 0x66,    /*                     (NEC PC98) */
        Kana            = 0x70,    /* (Japanese keyboard)            */
        ABNT_C1         = 0x73,    /* /? on Brazilian keyboard */
        Convert         = 0x79,    /* (Japanese keyboard)            */
        NoConvert       = 0x7B,    /* (Japanese keyboard)            */
        Yen             = 0x7D,    /* (Japanese keyboard)            */
        ABNT_C2         = 0x7E,    /* NumPad . on Brazilian keyboard */
        NumPadEquals    = 0x8D,    /* = on numeric keypad (NEC PC98) */
        PrevTrack       = 0x90,    /* Previous Track (CIRCUMFLEX on Japanese keyboard) */
        AT              = 0x91,    /*                     (NEC PC98) */
        Colon           = 0x92,    /*                     (NEC PC98) */
        UnderLine       = 0x93,    /*                     (NEC PC98) */
        Kanji           = 0x94,    /* (Japanese keyboard)            */
        Stop            = 0x95,    /*                     (NEC PC98) */
        AX              = 0x96,    /*                     (Japan AX) */
        Unlabeled       = 0x97,    /*                        (J3100) */
        NextTrack       = 0x99,    /* Next Track */
        NumPadEnter     = 0x9C,    /* Enter on numeric keypad */
        RCcontrol       = 0x9D,
        Mute            = 0xA0,    /* Mute */
        Calculator      = 0xA1,    /* Calculator */
        PlayPause       = 0xA2,    /* Play / Pause */
        MediaStop       = 0xA4,    /* Media Stop */
        VolumeDown      = 0xAE,    /* Volume - */
        VolumeUp        = 0xB0,    /* Volume + */
        WebHome         = 0xB2,    /* Web home */
        NumPadComma     = 0xB3,    /* , on numeric keypad (NEC PC98) */
        Divide          = 0xB5,    /* / on numeric keypad */
        SysRq           = 0xB7,
        RMenu           = 0xB8,    /* right Alt */
        Pause           = 0xC5,    /* Pause */
        Home            = 0xC7,    /* Home on arrow keypad */
        Up              = 0xC8,    /* UpArrow on arrow keypad */
        Prior           = 0xC9,    /* PgUp on arrow keypad */
        Left            = 0xCB,    /* LeftArrow on arrow keypad */
        Right           = 0xCD,    /* RightArrow on arrow keypad */
        End             = 0xCF,    /* End on arrow keypad */
        Down            = 0xD0,    /* DownArrow on arrow keypad */
        Next            = 0xD1,    /* PgDn on arrow keypad */
        Insert          = 0xD2,    /* Insert on arrow keypad */
        Delete          = 0xD3,    /* Delete on arrow keypad */
        LWin            = 0xDB,    /* Left Windows key */
        RWin            = 0xDC,    /* Right Windows key */
        Apps            = 0xDD,    /* AppMenu key */
        Power           = 0xDE,    /* System Power */
        Sleep           = 0xDF,    /* System Sleep */
        Wake            = 0xE3,    /* System Wake */
        WebSearch       = 0xE5,    /* Web Search */
        WebFavorites    = 0xE6,    /* Web Favorites */
        WebRefresh      = 0xE7,    /* Web Refresh */
        WebStop         = 0xE8,    /* Web Stop */
        WebForward      = 0xE9,    /* Web Forward */
        WebBack         = 0xEA,    /* Web Back */
        MyComputer      = 0xEB,    /* My Computer */
        Mail            = 0xEC,    /* Mail */
        MediaSelect     = 0xED,    /* Media Select */
        RUp             = 0xEE,
        RDown           = 0xEF,
        RLeft           = 0xF0,
        RRight          = 0xF1
    #endif   
    XIMERA_ENUM_END(KeyCode)

    //! \brief Codes of the buttons that can be used in a Mouse input device.
    XIMERA_ENUM(MouseCode)
        // Control keys
        Left             = 0x00,
        Right            = 0x01,
        Middle           = 0x02,
        Aux0             = 0x03,
        Aux1             = 0x04,
        Aux2             = 0x05,
        Aux3             = 0x06,
        Aux4             = 0x07
    XIMERA_ENUM_END(MouseCode)

    Char const KeyChars[] = 
    {
        0, 0,
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=',
        0, 0,
        'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 13,
        0,
        'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
        0,
        '\\', 'z', 'x',    'c', 'v', 'b', 'n', 'm', ',', '.', '/',
        0,
        '*',
        0,
        ' ',
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.'
    };

    Char const KeyCharsShift[] = 
    {
        0, 0,
        '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+',
        0, 0,
        'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 13,
        0,
        'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
        0,
        '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?',
        0,
        '*',
        0,
        ' ',
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.'
    };

    inline Char keyCodeToChar(KeyCode code, bool shift = false)
    {
        if (code <= KeyCode::Decimal)
            return shift ? KeyCharsShift[code] : KeyChars[code];

        return 0;
    }
}}

// -----------------------------------------------------------

#endif
